/**
 * 
 */
package com.vision.core.sv.serv.rpc;

import static com.vision.core.cm.data.AdminPermissions.CreateCompany;
import static com.vision.core.cm.data.AdminPermissions.DeleteCompany;
import static com.vision.core.cm.data.AdminPermissions.UpdateCompany;
import static com.vision.core.cm.data.AdminPermissions.ViewCompany;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.vision.core.cm.data.Domain;
import com.vision.core.cm.db.data.Company;
import com.vision.core.cm.db.data.Company.CompanyStatus;
import com.vision.core.cm.db.data.CompanyGroup;
import com.vision.core.cm.exception.DataNotFoundException;
import com.vision.core.cm.exception.RpcException;
import com.vision.core.cm.serv.rpc.CompanyService;
import com.vision.core.sv.db.mgr.IDataManager;
import com.vision.core.sv.serv.util.ServletUtils;

/**
 * @author Mark
 *
 */
@Service("companies")
public class CompanyServiceImpl extends AbstractServiceImpl<Company> implements CompanyService {

	private static final long serialVersionUID = 1L;
	
	private static final Logger log = LoggerFactory.getLogger(CompanyServiceImpl.class);
	
	private static final String MESSAGE_NOT_FOUND = "The Company does not exist.";
	
	public CompanyServiceImpl() {
		initGilead();
	}

	@Autowired
	@Qualifier("companyManager")
	@Override
	public void setDataManager(IDataManager<Company> dataManager) {
		super.setDataManager(dataManager);
	}
	
	@SuppressWarnings("unused")
	@Autowired
	@Qualifier("companyGroupManager")
	private IDataManager<CompanyGroup> companyGroupManager;
	
	@Transactional
	@Override
	public Company create(Company company) throws RpcException {
		checkPermissions(CreateCompany);
		
		company.setStatus(CompanyStatus.ACTIVE);
		
		log.debug("Creating company: {}", company.getName());
		
		Company result = super.create(company);
		
		logCreate(result);
		
		return result;
	}
	
	@Transactional
	@Override
	public Company update(Company company) throws RpcException {
		checkPermissions(UpdateCompany);
		Company existing = checkExisting(company);
		
		log.debug("Updating company: {}", company.getName());
		
		Company result = super.update(company);
		
		logUpdate(existing, result);
		
		return result;
	}
	
	@Transactional
	@Override
	public Company delete(Company company) throws RpcException {
		checkPermissions(DeleteCompany);
		Company existing = checkExisting(company);
		
		log.debug("Deleting company: {}", existing.getName());
		
		Company result = super.delete(existing);
		
		logDelete(result);
		
		return result;
	}
	
	@Override
	public List<Company> getAll() throws RpcException {
		checkPermissions(ViewCompany);
		
//		List<Company> all = super.getAll();
//		
//		// Limit based on the companies assigned to user
//		Set<Company> userCompanies = ServletUtils.getLoggedInUser().getCompanies();
//		all.removeAll(userCompanies);
//		
//		return all;
		
		Set<Company> userCompanies = ServletUtils.getLoggedInUser().getCompanies();
		return new ArrayList<Company>(userCompanies);
	}
	
	@Override
	public List<Company> getNameAndIdOnly() throws RpcException {
//		ISimpleCriteria crit = SimpleCriteria.forClass(Company.class);
//		String[] properties = new String[]{ "id", "code", "name" };
//		crit.properties(properties); // Retrieve only id, code, and name
//		crit.asc("name");
//		crit.setResultTransformer(SimpleTransformer.create(Company.class, properties));
//		
//		List<Company> list = getTemplate().findByCriteria(crit.getDetached());
//		return list;
		
		Set<Company> userCompanies = ServletUtils.getLoggedInUser().getCompanies();
		return new ArrayList<Company>(userCompanies);
	}

	@Transactional
	@Override
	public Company activate(Company company) throws RpcException {
		checkPermissions(UpdateCompany);
		Company existing = checkExisting(company);
		
		existing.setStatus(CompanyStatus.ACTIVE);
		
		log.debug("Activating company: {}", existing.getName());
		
		Company result = super.update(existing);
		
		logUpdate(existing, result);
		
		return result;
	}

	@Transactional
	@Override
	public Company deactivate(Company entity) throws RpcException {
		checkPermissions(UpdateCompany);
		Company existing = checkExisting(entity);
		existing.setStatus(CompanyStatus.DEACTIVATED);
		
		log.debug("Deactivating company: {}", existing.getName());
		
		Company result = super.update(existing);
		
		logUpdate(existing, result);
		
		return result;
	}	
	
	@Override
	protected Domain getDomain() {
		return Domain.COMPANY;
	}

	// Helpers *****************************************************************
	
	protected Company checkExisting(Company param) throws DataNotFoundException {
		Company existing = getDataManager().getById(param.getId());
		if (existing == null)
			throw new DataNotFoundException(MESSAGE_NOT_FOUND);
		return existing;
	}
	
}
